import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not, Repository } from 'typeorm';
import { WithdrawingEnum } from '../wxUser/wxUser.enum';
import { Profit } from './profit.entity';
import { profitEnum } from './profit.enum';
import { Questions } from '../questions/questions.entity';
import DataBase from 'src/config/database';
import { AnswerReportErrors } from '../answerReportErrors/answerReportErrors.entity';
import { ReportSourceEnum, TypeEnum } from '../answerReportErrors/answerReportErrors.enum';
import { RewardSuccess } from '../rewardSuccess/rewardSuccess.entity';
import { Reward } from '../reward/reward.entity';
import { payStatusEnum } from '../reward/reward.enum';
import { ProfitRefund } from '../profitRefund/profitRefund.entity';
import { profitRefundStatusEnum } from '../profitRefund/profitRefund.enum';
import { WXAPI } from 'src/common/wx_api';
import { Notices } from '../notices/notices.entity';
import { NoticeCheckEnum, NoticeTypeEnum } from '../notices/notices.enum';
import { Answer } from '../answer/answer.entity';
import { WsStartGateway } from '../ws/ws.gateway';
let WXAPIOBJ = new WXAPI()

@Injectable()
export class ProfitService {
  constructor(
    @InjectRepository(Profit)
    private repository: Repository<Profit>,
    @InjectRepository(Questions)
    private questionsRepository: Repository<Questions>,
    @InjectRepository(AnswerReportErrors)
    private answerReportErrorsRepository: Repository<AnswerReportErrors>,
    @InjectRepository(RewardSuccess)
    private rewardSuccessRepository: Repository<RewardSuccess>,
    @InjectRepository(Reward)
    private rewardRepository: Repository<Reward>,
    @InjectRepository(ProfitRefund)
    private profitRefundRepository: Repository<ProfitRefund>,
    @InjectRepository(Answer)
    private answerRepository: Repository<Answer>,
    @InjectRepository(Notices)
    private noticesRepository: Repository<Notices>,
    private readonly wsStartGateway: WsStartGateway,
  ) {}


  /**
   * 查询用户可提现的金额
   * @param wx_user 
   * @returns 
   */
  async findWithdrawal(wx_user: string){
    let dataList = await this.repository.query(`
      select sum(totalPrice) as totalPrice from (
        select sum(unit_price) as totalPrice from profit 
        where status = 1 and author_wx_user = ?
        union all
        select sum(unit_price) as totalPrice from profit_unlock_home 
        inner join video on video.id = profit_unlock_home.video_id
        where profit_unlock_home.status = 1 and video.wx_user = ? 
      ) a
    `,[wx_user, wx_user])
    //提现记录
    let tx = await this.repository.query(`
      select sum(use_amount) as totalPrice from wallet_flow where status = 1 and wx_user = ?
    `,[wx_user])

    //提问的人返还悬赏金

    //追加悬赏的人返还悬赏金


    //追加选上的人获得普通收益


    //查询用户是否能提现
    let isOutAccount = await this.repository.query(`
      select withdrawing from wx_user where openid = ?
    `,[wx_user])
    let totalPrice = 0,withdrawing = false
    if(isOutAccount.length > 0){
      withdrawing = isOutAccount[0].withdrawing == WithdrawingEnum.withdrawing ? true : false
    }
    if(dataList.length > 0){
      totalPrice = dataList[0].totalPrice
    }

    if(tx.length > 0){
      totalPrice = totalPrice - tx[0].totalPrice
    }

    // if(rewardPrice.length > 0){
    //   totalPrice = totalPrice + Number(rewardPrice[0].totalPrice)
    // }

    return {
      totalPrice:totalPrice,
      withdrawing:withdrawing
    }
  }

  /**
   * 查询所有用户的收入
   */
  async findAll_By_User(skip: number, take: number, wx_user: string): Promise<{data:[],totalPrice:0}>{
    let dataList = await this.repository.query(`
      select * from (
        select substring(a.create_time, 1, 10) create_time,sum(a.unit_price) totalPrice from profit a
        where a.status = 1 and a.author_wx_user = ?
        group by substring(a.create_time, 1, 10)
        union all
        select substring(a.create_time, 1, 10) create_time,sum(a.unit_price) totalPrice from profit_unlock_home a
        inner join video on video.id = a.video_id
        where a.status = 1 and video.wx_user = ?
        group by substring(a.create_time, 1, 10)
      ) a
      order by substring(a.create_time, 1, 10) desc
      limit ?,?
    `,[wx_user, wx_user, skip, take])

    let totalPrice = await this.repository.query(`
      select sum(totalPrice) totalPrice from (
        select sum(a.unit_price) totalPrice from profit a
        where a.status = 1 and a.author_wx_user = ?
        union all
        select sum(a.unit_price) totalPrice from profit_unlock_home a
        inner join video on video.id = a.video_id
        where a.status = 1 and video.wx_user = ?
      ) a
    `,[wx_user, wx_user])
    return {data:dataList,totalPrice:totalPrice[0].totalPrice}

  }
  /**
   * 查询某个作品的所有收入记录
   * @param skip
   * @param take
   * @param wallet_flow_id
   * @returns
   */
  async findAll_By_Video(skip: number, take: number, video_id: number): Promise<{data:[],totalPrice:0}>{
    let dataList = await this.repository.query(`
      select * from (
        select substring(a.create_time, 1, 10) create_time,sum(a.unit_price) totalPrice from profit a
        inner join answer b on b.id = a.answer_id
        where b.video_id = ? and a.status = 1 and a.unit_price > 0
        group by substring(a.create_time, 1, 10)
        union all
        select substring(a.create_time, 1, 10) create_time,sum(a.unit_price) totalPrice from profit_unlock_home a
        where a.video_id = ? and a.status = 1 and a.unit_price > 0
        group by substring(a.create_time, 1, 10)
      ) a
      order by a.create_time desc
      limit ?,?
    `,[video_id, video_id, skip, take])

    let totalPrice = await this.repository.query(`
      select sum(a.totalPrice) as totalPrice from (
        select sum(a.unit_price) totalPrice from profit a
        inner join answer b on b.id = a.answer_id
        where b.video_id = ? and a.status = 1 and a.unit_price > 0
        union all
        select sum(a.unit_price) totalPrice from profit_unlock_home a
        where a.video_id = ? and a.status = 1 and a.unit_price > 0
      ) a
    `,[video_id, video_id])
    return {data:dataList,totalPrice:totalPrice[0].totalPrice}
  }

  /**
   * 查询提现详情
   * @param skip
   * @param take
   * @param wallet_id
   * @returns
   */
  findAll_By_Wallet(skip: number, take: number, wallet_flow_id: number): Promise<Profit[]>{
    return this.repository.query(`
      select a.*,e.video_key,e.id from profit a
      inner join wallet_flow b on b.id = a.wallflow_id
      inner join answer c on c.id = a.answer_id
      inner join video e on e.id = c.video_id
      where b.id = ?
      order by a.update_time,a.create_time desc
      limit ?,?
    `,[wallet_flow_id, skip, take])
  }

  /**
   * 查询用户的收益（原创/非原创）
   * @param skip
   * @param take
   * @param wx_user
   * @param original
   * @returns
   */
  async findAll_My_By_Original(skip: number, take: number, wx_user: string,original: number): Promise<Profit[]>{
    let dataList: any = []
    if(original == 1){
      
      // select * from video a
      // where a.wx_user = ? and a.original = 1 and a.check = 1
      // order by a.id desc
      dataList = await this.repository.query(`
        select video.*
        from answer
        inner join video on video.id = answer.video_id
        where (answer.type = 2 or answer.type = 3 or answer.type = 4) and answer.check = 1 and answer.wx_user = ? and video.check = 1
        order by video.id desc
        limit ?,?
      `,[wx_user, skip, take])
      // dataList.filter(e => e.overseas === 1).map(e => delete e.id)
    }else{
      dataList = await this.repository.query(`
        select a.* from answer a
        inner join video c on c.id = a.video_id
        where a.check = 1 and a.wx_user = ?
          and c.wx_user != a.wx_user
         
        order by a.id desc
        limit ?,?
      `,[wx_user, skip, take])
    }
    return dataList
  }

  /**
   * 创建一个收益
   * @param data
   * @returns
   */
  async create(data: Profit): Promise<Profit> {
    return await this.repository.save(data);
  }

  /**
   * 查询用户所有未提现的收益
   * @param wx_user
   * @returns
   */
  async findAll_Entry(wx_user: string): Promise<Profit[]> {
    return await this.repository.find({where:{author_wx_user:wx_user,status:profitEnum.entry}});
  }

  /**
   * 发起退款
   * @param wx_user 
   * @param answer_id 
   */
  async refund(wx_user: string, answer_id: number, errorType: TypeEnum, platform: string, account: string, ic_name: string,
    avatar_id: string, avatar_img: string, img: string, img_id: string){
    let db: DataBase = new DataBase()
    let connection = await db.getConnection()
    const queryRunner = connection.createQueryRunner()
    await queryRunner.connect()
    // 开始事务
    await queryRunner.startTransaction()
    try {
      await this.repository.createQueryBuilder(null, queryRunner)
        .update({ status: profitEnum.refoundIng, update_time: new Date()})
        .where({ use_wx_user: wx_user, answer_id: answer_id })
        .execute()
      //添加报错信息
      let answerReportError = new AnswerReportErrors()
      answerReportError.wx_user = wx_user
      answerReportError.answer_id = answer_id
      answerReportError.create_time = new Date()
      answerReportError.type = errorType
      answerReportError.platform = platform
      answerReportError.account = account
      answerReportError.ic_name = ic_name
      answerReportError.avatar_id = avatar_id
      answerReportError.avatar_img = avatar_img
      answerReportError.img = img
      answerReportError.img_id = img_id
      answerReportError.source = ReportSourceEnum.refund
      await this.answerReportErrorsRepository.createQueryBuilder(null, queryRunner)
        .insert()
        .into(AnswerReportErrors)
        .values(answerReportError)
        .execute()
    
      await queryRunner.commitTransaction()
      await queryRunner.release();
    } catch (err) {
      // 有错误做出回滚更改
      await queryRunner.rollbackTransaction()
      await queryRunner.release();
      return err
    }

  }

  /**
   * 同意退款
   * @param wx_user 
   * @param answer_id 
   * @returns 
   */
  async refundSuccess(id: number){
    //查询收益详情
    let findProfit = await this.repository.findOne({where:{id: id}})
    if(!findProfit){
      return '收益不存在'
    }
    //查询视频
    let findAnswer = await this.answerRepository.findOne({where:{id: findProfit.answer_id}})
    //查找同提问
    let findQuestion: Questions[] = await this.questionsRepository.query(`
      select questions.* from questions
      inner join answer on answer.video_id = questions.video_id
      where questions.wx_user = ? and answer.id = ?
    `,[findProfit.use_wx_user, findProfit.answer_id])
    //查询是否有悬赏
    let findReward: RewardSuccess[] = await this.rewardSuccessRepository.query(`
      select * from reward_success
      inner join answer on answer.video_id = reward_success.video_id
      where answer.id = ? and reward_success.wx_user = ?
    `,[findProfit.answer_id, findProfit.use_wx_user])

    let db: DataBase = new DataBase()
    let connection = await db.getConnection()
    const queryRunner = connection.createQueryRunner()
    await queryRunner.connect()
    // 开始事务
    await queryRunner.startTransaction()
    try {
      //修改同提问答案收到的时间
      if(findQuestion.length > 0){
        //清空同提问时间
        await this.questionsRepository.createQueryBuilder(null, queryRunner)
          .update({answer_time: null, post_answer: 0})
          .where({id: findQuestion[0].id})
          .execute()

          console.log(findReward,'finreww')
        //删除悬赏
        if(findReward.length > 0){
          await this.rewardSuccessRepository.createQueryBuilder(null, queryRunner)
            .delete()
            .where({video_id: findReward[0].video_id, wx_user: findProfit.use_wx_user})
            .execute()
          await this.rewardRepository.createQueryBuilder(null, queryRunner)
            .update({pay_status: payStatusEnum.reject})
            .where({video_id: findReward[0].video_id, wx_user: findProfit.use_wx_user})
            .execute()
        }
      }
      
      await this.repository.createQueryBuilder(null, queryRunner)
        .delete()
        .where({id: id})
        .execute()

      // if(findReward.length == 0){
        //添加收益退款记录
        let profitRefund = new ProfitRefund()
        profitRefund.answer_id = findProfit.answer_id
        profitRefund.author_wx_user = findProfit.author_wx_user
        profitRefund.use_wx_user = findProfit.use_wx_user
        profitRefund.status = profitRefundStatusEnum.refoundSuccess
        profitRefund.notes = findProfit.notes
        profitRefund.service_charge = findProfit.service_charge
        profitRefund.unit_price = findProfit.unit_price
        profitRefund.type = findProfit.type
        profitRefund.update_time = findProfit.update_time
        profitRefund.create_time = findProfit.create_time
        profitRefund.delivery_time = findProfit.create_time
        await this.profitRefundRepository.createQueryBuilder(null, queryRunner)
          .insert()
          .into(ProfitRefund)
          .values(profitRefund)
          .execute()
      // }
      //通知申请人已退款
      let notice = new Notices()
      notice.answer_id = findProfit.answer_id
      notice.check = NoticeCheckEnum.yes
      notice.create_time = new Date()
      notice.type = NoticeTypeEnum.refund_accept
      notice.video_id = findAnswer.video_id
      notice.wx_user = findProfit.use_wx_user
      await this.noticesRepository.createQueryBuilder(null, queryRunner).insert().into(Notices).values(notice).execute()
      WXAPIOBJ.clearPayWallet(findProfit.use_wx_user)
      
      await queryRunner.commitTransaction()
      await queryRunner.release();

      this.wsStartGateway.postUpdateNotice(notice.wx_user)
      this.wsStartGateway.postUpdateVideo(findAnswer.video_id)

    } catch (err) {
      // 有错误做出回滚更改
      await queryRunner.rollbackTransaction()
      await queryRunner.release();
      return err
    }
  }

  /**
   * 拒绝退款
   * @param wx_user 
   * @param answer_id 
   * @returns 
   */
  async refundReject(id: number, reject_reason: number){
    //查询收益详情
    let findProfit = await this.repository.findOne({where:{id: id}})
    if(!findProfit){
      return '收益不存在'
    }
    let findAnswer = await this.answerRepository.findOne({where:{id: findProfit.answer_id}})
    
    let db: DataBase = new DataBase()
    let connection = await db.getConnection()
    const queryRunner = connection.createQueryRunner()
    await queryRunner.connect()
    // 开始事务
    await queryRunner.startTransaction()
    try {
      await this.repository.createQueryBuilder(null, queryRunner).update({status: profitEnum.entry, update_time: new Date(), reject_reason: reject_reason}).where({id: id}).execute()
      //通知申请人拒绝退款
      let notice = new Notices()
      notice.answer_id = findProfit.answer_id
      notice.check = NoticeCheckEnum.yes
      notice.create_time = new Date()
      notice.type = NoticeTypeEnum.refund_reject
      notice.video_id = findAnswer.video_id
      notice.wx_user = findProfit.use_wx_user
      notice.reject_reason = reject_reason
      await this.noticesRepository.createQueryBuilder(null, queryRunner).insert().into(Notices).values(notice).execute()
      
      await queryRunner.commitTransaction()
      await queryRunner.release();

      
      this.wsStartGateway.postUpdateNotice(notice.wx_user)
      this.wsStartGateway.postUpdateVideo(findAnswer.video_id)
    } catch (err) {
      // 有错误做出回滚更改
      await queryRunner.rollbackTransaction()
      await queryRunner.release();
      return err
    }

  }

  /**
   * 查询视频下所有退款申请
   * @param video_id 
   */
  async refundListByVideoId(skip: number, take: number, video_id: number){
    let dataList = await this.repository.query(`
      select p.* from profit p
      inner join answer b on b.id = p.answer_id
      where (p.status = 3 or p.status = 4) and b.video_id = ?
      order by p.update_time desc
      limit ?,?
    `,[video_id, skip, take])
    
    let total = await this.repository.query(`
      select count(1) as total from profit p
      inner join answer b on b.id = p.answer_id
      where (p.status = 3 or p.status = 4) and b.video_id = ?
    `,[video_id])

    return {data:dataList,total: Number(total[0].total)}
  }

  async refundList(skip: number, take: number, video_id: number){
    let params = [skip, take]
    let sql = `select p.*,video.id as video_id,internet_celebrity.name as ic_name, internet_celebrity.img, 
        internet_celebrity.avatar_img,platform.platform,internet_celebrity.account, video.video_url as video_url,
        video.video_url_source, video.video_cover, video.type as video_type
      from profit p
      inner join answer b on b.id = p.answer_id
      left join video on video.id = b.video_id
      left join internet_celebrity on internet_celebrity.ic_group = video.ic_group
      left join platform on platform.id = internet_celebrity.platform
      where (p.status = 3 or p.status = 4) and p.type != 0
      
    `
    let sqlTotal = `
      select count(1) as total from profit p
      inner join answer b on b.id = p.answer_id
      left join video on video.id = b.video_id
      where (p.status = 3 or p.status = 4) and p.type != 0
    `
    let paramsTotal = []
    if(video_id){
      params.splice(0,0,video_id)
      sql += ' and video.id = ? order by p.update_time asc limit ?,?'
      paramsTotal.push(video_id)
      sqlTotal += ' and video.id = ?'
    }else{
      sql += ' order by p.update_time asc limit ?,?'
    }
    let dataList = await this.repository.query(sql, params)
    
    let total = await this.repository.query(sqlTotal, paramsTotal)

    return {data:dataList,total: Number(total[0].total)}
  }
}
